package kz.kstu.aecdemo.desktop.ui.dialog;

import kz.kstu.aec.Authenticator;
import kz.kstu.aec.model.ClientData;
import kz.kstu.aec.model.AuthenticationData;
import kz.kstu.aec.model.Point2D;
import kz.kstu.aecdemo.app.context.ClientContext;
import kz.kstu.aecdemo.app.delegate.api.AccountDelegate;
import kz.kstu.aecdemo.app.delegate.impl.AccountDelegateImpl;
import kz.kstu.aecdemo.business.entity.security.AbstractAccount;
import kz.kstu.aecdemo.business.util.StringUtil;
import kz.kstu.aecdemo.desktop.util.GUIUtils;
import org.apache.log4j.Logger;

import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.LoginException;
import javax.swing.*;
import java.awt.event.*;
import java.math.BigInteger;

public class ChangePasswordDialog extends JDialog {

    private static final String TITLE = "Смена пароля";

    private static final int WIDTH = 400;
    private static final int HEIGHT = 200;

    private static final String PASSWORDS_NOT_MATCH = "Введенные пароли не совпадают";
    private static final String EMPTY_PASSWORD = "Пароль не может быть пустым";
    private static final String PASSWORD_SUCCESSFULLY_CHANGED = "Пароль успешно изменен";
    private static final String INCORRECT_LOGIN_OR_PASSWORD = "Логин и/или пароль указан неверно";
    private static final String LOGIN_NOT_FOUND = "Указанный логин не найден";

    private JPanel contentPane;
    private JButton buttonOK;
    private JButton buttonCancel;
    private JPasswordField oldPasswordField;
    private JPasswordField confirmNewPasswordField;
    private JPasswordField newPasswordField;

    public ChangePasswordDialog() {
    }

    public void changePassword() {
        initStaticComponents();
    }

    private void initStaticComponents() {
        setContentPane(contentPane);
        setModal(true);
        setResizable(false);
        setSize(WIDTH, HEIGHT);
        setTitle(TITLE);
        initListeners();
        getRootPane().setDefaultButton(buttonOK);
        GUIUtils.centerAndShow(this);
    }

    private void initListeners() {
        buttonOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onOk();
            }
        });

        buttonCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });

        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });

        contentPane.registerKeyboardAction(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        onCancel();
                    }
                }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    }

    private void onOk() {

        String oldPassword = new String(oldPasswordField.getPassword());
        String newPassword = new String(newPasswordField.getPassword());
        String confirmedNewPassword= new String(confirmNewPasswordField.getPassword());

        if (StringUtil.isEmptyString(newPassword)) {
            shoMessage(EMPTY_PASSWORD, JOptionPane.ERROR_MESSAGE);
            return;
        }

        if (!confirmedNewPassword.equals(newPassword)) {
            shoMessage(PASSWORDS_NOT_MATCH, JOptionPane.ERROR_MESSAGE);
            return;
        }

        AccountDelegate accountDelegate = new AccountDelegateImpl();
        AbstractAccount account = ClientContext.getInstance().getAccount();
        String login = account.getLogin();
        try {
            ClientData clientData = new ClientData(login, oldPassword);
            Authenticator authenticator = Authenticator.getInstance();
            BigInteger authenticationNumber = accountDelegate.getAuthenticationNumber(login);
            AuthenticationData authenticationData = authenticator.getAuthenticationData(clientData, authenticationNumber);
            accountDelegate.login(authenticationData);

            ClientData newClientData = new ClientData(login, newPassword);
            Point2D publicKey = authenticator.getPublicKey(newClientData);
            accountDelegate.changePassword(login, publicKey);

            shoMessage(PASSWORD_SUCCESSFULLY_CHANGED, JOptionPane.INFORMATION_MESSAGE);
            dispose();
        } catch (AccountNotFoundException e) {
            shoMessage(LOGIN_NOT_FOUND, JOptionPane.ERROR_MESSAGE);
        } catch (LoginException e) {
            shoMessage(INCORRECT_LOGIN_OR_PASSWORD, JOptionPane.ERROR_MESSAGE);
        }
    }

    public void shoMessage(String message, int messageType) {
        JOptionPane.showMessageDialog(this, message, TITLE, messageType);
    }

    private void onCancel() {
        dispose();
    }
}
